Pod Hook

    实际上 Kubernetes 为我们的容器提供了生命周期钩子的,就是我们说的Pod Hook,Pod Hook 是由 kubelet 发起的,当容器中的进程启动前或者容器中的进程终止之前运行,这是包含在容器的生命周期之中。我们可以同时为 Pod 中的所有容器都配置 hook。

    Kubernetes 为我们提供了两种钩子函数:

    • PostStart:这个钩子在容器创建后立即执行。但是,并不能保证钩子将在容器ENTRYPOINT之前运行,因为没有参数传递给处理程序。主要用于资源部署、环境准备等。不过需要注意的是如果钩子花费太长时间以至于不能运行或者挂起, 容器将不能达到running状态。
    • PreStop:这个钩子在容器终止之前立即被调用。它是阻塞的,意味着它是同步的, 所以它必须在删除容器的调用发出之前完成。主要用于优雅关闭应用程序、通知其他系统等。如果钩子在执行期间挂起, Pod阶段将停留在running状态并且永不会达到failed状态。

    另外我们有两种方式来实现上面的钩子函数:

    • Exec - 用于执行一段特定的命令,不过要注意的是该命令消耗的资源会被计入容器。
    • HTTP - 对容器上的特定的端点执行HTTP请求。

    以下示例中,定义了一个Nginx Pod,其中设置了PostStart钩子函数,即在容器创建成功后,写入一句话到/usr/share/message文件中。

    示例2 优雅删除资源对象

    • 默认:K8S 通知 node 执行docker stop命令,docker 会先向容器中PID为1的进程发送系统信号SIGTERM,然后等待容器中的应用程序终止执行,如果等待时间达到设定的超时时间,或者默认超时时间(30s),会继续发送SIGKILL的系统信号强行 kill 掉进程。
    • 使用 pod 生命周期(利用PreStop回调函数),它执行在发送终止信号之前。

    默认所有的优雅退出时间都在30秒内。kubectl delete 命令支持 --grace-period=<seconds>选项,这个选项允许用户用他们自己指定的值覆盖默认值。值’0’代表 强制删除 pod. 在 kubectl 1.5 及以上的版本里,执行强制删除时必须同时指定 --force --grace-period=0

    强制删除一个 pod 是从集群状态还有 etcd 里立刻删除这个 pod。 当 Pod 被强制删除时, api 服务器不会等待来自 Pod 所在节点上的 kubelet 的确认信息:pod 已经被终止。在 API 里 pod 会被立刻删除,在节点上, pods 被设置成立刻终止后,在强行杀掉前还会有一个很小的宽限期。

    1. kind: Pod
    2. metadata:
    3. name: hook-demo2
    4. spec:
    5. containers:
    6. image: nginx
    7. lifecycle:
    8. preStop:
    9. exec:
    10. command: ["/usr/sbin/nginx","-s","quit"]
    11. ---
    12. apiVersion: v1
    13. kind: Pod
    14. metadata:
    15. name: hook-demo2
    16. labels:
    17. app: hook
    18. - name: hook-demo2
    19. image: nginx
    20. ports:
    21. - name: webport
    22. containerPort: 80
    23. volumeMounts:
    24. - name: message
    25. mountPath: /usr/share/
    26. lifecycle:
    27. preStop:
    28. exec:
    29. command: ['/bin/sh', '-c', 'echo Hello from the preStop Handler > /usr/share/message']
    30. volumes:
    31. - name: message
    32. path: /tmp

    另外Hook调用的日志没有暴露个给 Pod 的 event,所以只能通过describe命令来获取,如果有错误将可以看到或FailedPreStopHook这样的 event。